#ifndef _MY_ALLOCATOR_H_
#define _MY_ALLOCATOR_H_

#include <cstddef>
#include <iostream>
#include <limits>
#include <new>

using namespace std;

template<typename T>
struct my_allocator {
	typedef T value_type;
	typedef T* pointer;
	typedef const T* const_pointer;
	typedef T& reference;
	typedef const T& const_reference;
	typedef size_t size_type;
	typedef ptrdiff_t difference_type;
	template<typename U> struct rebind {typedef my_allocator<U> other;};
	
	my_allocator() {
		// bloc vide
	}
	
	my_allocator(const my_allocator&) {
		// bloc vide
	}
	
	template<typename U>
	my_allocator(const my_allocator<U>&) {
		// bloc vide
	}
	
	~my_allocator() {
		// bloc vide
	}
	
	pointer address(reference x) const {
	#ifdef MAP
		cout << "Appel d'address reference" << endl;
	#endif
		return &x;
	}
	
	const_pointer address(const_reference x) const {
	#ifdef MAP
		cout << "Appel d'address const_reference" << endl;
	#endif
		return &x;
	}
	
	size_type max_size() const {
		return numeric_limits<size_type>::max() / (sizeof(T));
	}
	
	void construct(pointer p, const_reference val) {
	#ifdef MAP
		cout << "Appel de construct" << endl;
	#endif
		new ((void*) p) T(val);
	}
	
	void destroy(pointer p) {
	#ifdef MAP
		cout << "Appel de destroy" << endl;
	#endif
		((T*) p)->~T();
	}
	
	pointer allocate(size_type n, void* hint = 0) {
	#ifdef MAP
		cout << "Appel d'allocate, n = " << n << endl;
	#endif
		return (T*)::operator new (n * sizeof(T));
	}
	
	void deallocate(pointer p, size_type n) {
	#ifdef MAP
		cout << "Appel de deallocate, n = " << n << endl;
	#endif
		for (size_type i = 0; i < n; i++) {
			::operator delete ((void*) (p + i), nothrow);
		}
	}
	
	bool operator == (const my_allocator<T>& a) {
		return true;
	}
	
	bool operator != (const my_allocator<T>& a) {
		return !operator == (a);
	}
};

#endif

